#pragma once

#include "MessagePubSubTypes.h"
#include "ComDefine.h"
#include <fastdds/dds/domain/DomainParticipant.hpp>
#include <fastdds/dds/publisher/Publisher.hpp>
#include <fastdds/dds/topic/Topic.hpp>
#include <fastdds/dds/publisher/DataWriter.hpp>
#include <fastdds/dds/publisher/DataWriterListener.hpp>
#include <thread>

class MessagePublisher
{
public:

    MessagePublisher();

    ~MessagePublisher();
    virtual bool init(InitParam param) = 0;

    //!Publish a sample
    virtual bool publish(bool waitForListener = true);

    //!Run for number samples
    void run(
        uint32_t samples,
        uint32_t sleep,
        uint32_t send_size);
    void stop();
protected:

    Message message_;

    eprosima::fastdds::dds::DomainParticipant* participant_;

    eprosima::fastdds::dds::Publisher* publisher_;

    eprosima::fastdds::dds::Topic* topic_;

    eprosima::fastdds::dds::DataWriter* writer_;

    std::atomic_bool stop_;

    class PubListener : public eprosima::fastdds::dds::DataWriterListener
    {
    public:

        PubListener()
            : matched_(0)
            , firstConnected_(false), zeroCopy_(false)
        {
        }

        ~PubListener() override
        {
        }

        void on_publication_matched(
            eprosima::fastdds::dds::DataWriter* writer,
            const eprosima::fastdds::dds::PublicationMatchedStatus& info) override;

        int matched_;

        bool firstConnected_;
        bool zeroCopy_;
    }
    listener_;

    virtual void runThread(
        uint32_t samples,
        uint32_t sleep,
        uint32_t send_size);

    eprosima::fastdds::dds::TypeSupport type_;

private:
    bool zeroCopyWriter(bool waitForListener);
    bool genericWriter(bool waitForListener);
private:
    std::thread thread_;
};



class MessagePublisher_tcp : public MessagePublisher
{
public:
    virtual bool init(InitParam param);
};
class MessagePublisher_udp : public MessagePublisher
{
public:
    virtual bool init(InitParam param);
};
class MessagePublisher_shm : public MessagePublisher
{
public:
    virtual bool init(InitParam param);
};
class MessagePublisher_ds : public MessagePublisher
{
public:
    virtual bool init(InitParam param);
};
